package com.atguigu.spring6.aop.annotation.aop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.Objects;

/**
 * @author: Michael
 * @date: 2025/5/15
 * @desc:
 */
@Component // ioc容器
@Aspect // 切面类
public class LogAspect {

    // execution(访问修饰符 增强方法返回类型 增强方法所在类全路径.方法名称(方法参数))

    @Pointcut("execution(* com.atguigu.spring6.aop.annotation.aop.CalculatorImpl.*(..))")
    public void pointCut(){}

    // 前置通知
    @Before("pointCut()")
    public void beforeMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        String args = Arrays.toString(joinPoint.getArgs());
        System.out.println("logger-->前置通知，方法名："+methodName+", 参数： "+args);
    }

    // 后置通知
    @After(value = "execution(* com.atguigu.spring6.aop.annotation.aop.CalculatorImpl.*(..))")
    public void afterMethod(JoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("logger-->后置通知，方法名："+methodName);
    }

    // 返回通知
    @AfterReturning(value = "execution(* com.atguigu.spring6.aop.annotation.aop.CalculatorImpl.*(..))", returning = "result")
    public void afterReturningMethod(JoinPoint joinPoint, Object result){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("logger-->返回通知，方法名："+methodName+", 返回结果： "+result);
    }

    // 异常通知
    @AfterThrowing(value = "execution(* com.atguigu.spring6.aop.annotation.aop.CalculatorImpl.*(..))", throwing = "ex")
    public void afterThrowingMethod(JoinPoint joinPoint, Throwable ex){
        String methodName = joinPoint.getSignature().getName();
        System.out.println("logger-->异常通知，方法名："+methodName+", 异常： "+ex);
    }

    // 环绕通知
    @Around(value = "execution(* com.atguigu.spring6.aop.annotation.aop.CalculatorImpl.*(..))")
    public Object aroundMethod(ProceedingJoinPoint joinPoint){
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        String argString = Arrays.toString(args);
        Object result = null;
        try{
            System.out.println("环绕通知==目标方法之前执行");

            result = joinPoint.proceed();

            System.out.println("环绕通知==目标方法返回值之后执行");
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            System.out.println("环绕通知==目标方法出现异常时执行");
        } finally {
            System.out.println("环绕通知==目标方法执行完毕");
        }
        return result;
    }
}
